-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MiqFileStorage interface and subclassing (with file splitting) #361
MiqFileStorage interface and subclassing (with file splitting) #361
Conversation
9362637
to
5255d29
Compare
f74ed02
to
1e77e77
Compare
Note for future reference: Looks like the travis failures are related to the following: https://stackoverflow.com/questions/10238298/ruby-on-linux-pty-goes-away-without-eof-raises-errnoeio Which is (briefly) mentioned in the sample code for https://ruby-doc.org/stdlib-2.2.3/libdoc/pty/rdoc/PTY.html#module-PTY-label-Example
Will look at adding something like this to the code to confirm that it fixes the issue on Travis (which does run Debian containers if I am not mistaken. Errors in Travis are very misleading because of the |
abfab9b
to
8476d86
Compare
# `remote_file_path` (might be everything if `remote_file_path` is a absolute | ||
# path) | ||
def mnt_point | ||
@mnt_point ||= File.expand_path(remote_file_path).sub(remote_file_path, "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After some thinking and looking at how to implement this in EvmDatabaseOps
, this is a bad way to implement this via memoization
.
Part of the reason to set @mnt_point
was to prevent changes to MiqGenericMountSession
, which doesn't use the accessor, but @mnt_point
directly in a lot of spots. But, there are plenty of times where remote_file_path
will not be set, and so generating @mnt_point
in this fashion will cause issues (possibly just error out) if it is set and memoized before a #add
call.
I have some ideas on how to do this better, but know that this implementation is probably going to change.
1b70fc5
to
c9dc4dc
Compare
c9dc4dc
to
3ee8fb6
Compare
34302a5
to
aea0477
Compare
This pull request is not mergeable. Please rebase and repush. |
aea0477
to
ca81761
Compare
5a500d3
to
5f5158e
Compare
# pipe generated by this method and passed in to the block as a file | ||
# location to the `input_stream`). | ||
# | ||
# In the non-block form, a source must be provioded as the first argument |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo, s/provioded/provided/
|
||
private | ||
|
||
def upload_single(file) # rubocop:disable Lint/UnusedMethodArgument |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you put a comment here describing how this should be implemented at a high level to work with splitting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, good call.
I will probably point to one of the existing classes for examples, but yeah, this should definitely be documented.
end | ||
end | ||
|
||
context "with slightly a slightly smaller input file than 10MB" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo, remove the first "slightly"
# the portions of the expanded path that already exist in the | ||
# `remote_file_path` (might be everything if `remote_file_path` is a absolute | ||
# path) | ||
def mnt_point |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic looks a bit complicated. Should we test this directly or you you think this is exercised enough through the existing tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is exercised (I believe) in the MiqLocalMountSession
tests, as I switch up what I pass to .add
in each of the different tests.
But I can target it specifically in that spec if you want (seems like it wouldn't be a bad idea).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a spec for this would be good. If nothing else it would be a good descriptor of what this method is actually doing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, after doing some investigating, I am going to try deleting this code and use a slightly different approach. I will report back, but that might be the easier route.
|
||
require 'aws-sdk' | ||
|
||
if defined? Aws::S3::GEM_VERSION # This constant doesn't exist in v2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I wouldn't want to push it just for this patch, but do we know if we are super far away from being able to use the new version as a whole? Would be curious to know how much effort that would be rather than forward porting this patch. @bronaghs Can you comment here or refer who would know about the aws-sdk version we are using?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we know if we are super far away from being able to use the new version as a whole?
I don't know personally, or if it has been considered at all.
I want to say there was something that was being done to update fog
in the recent future, and I thought that was potentially going to update the aws-sdk
, but I might be remembering incorrectly (Update: I was wrong... no surprise... It was for ManageIQ/manageiq#17258 and it was fog-google
, not AWS... oops)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the far future has arrived? #374
super(settings) | ||
|
||
# NOTE: This line to be removed once manageiq-ui-class region change implemented. | ||
@settings[:region] ||= "us-east-1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're here anyway ... @jerryk55 can we resolve this NOTE:
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my take, I am not sure if it is a bad thing to keep, and we might just be able to delete the comment. I simply ported over the comment from the old code since it seemed important.
But I would like @jerryk55 's opinion before I do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, but if we're keeping it, then we can probably drop the comment. Waiting on your input here @jerryk55
5f5158e
to
ab70c42
Compare
This comment has been minimized.
This comment has been minimized.
@carbonin I believe that I addressed most of your comments. |
ab70c42
to
5b2d047
Compare
scheme, _ = URI.split(URI::DEFAULT_PARSER.escape(opts[:uri])) | ||
klass = storage_interface_classes[scheme] | ||
|
||
raise ArgumentError, "Not a valid uri!" if klass.nil? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can be more descriptive here. Maybe something like:
raise ArgumentError, "#{scheme} is not a valid MiqFileStorage uri scheme. Accepted schemes are #{storage_interface_classes.keys}" if klass.nil?
7d5d866
to
4877422
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
end | ||
# `.join` will raise any errors from the thread, so we want to do that | ||
# here (if a thread exists of course). | ||
thread.join if block_given? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be more clear if we used the thread's existence as the condition rather than if the block was provided.
It's a bit confusing that I have to look into #handle_io_block
to figure out that a thread is only created if a block is provided.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, makes sense to me. I think I was just using that as the check elsewhere, but I think that is a reasonable change.
`MiqFileStorage` is meant to be an top level class for fetching classes that interface with `MiqFileStorage::Interface`. `MiqFileStorage::Interface` is meant to be the super class for all of the class to inherit from, to make sure that they conform to a spec that `MiqFileStorage` can work with.
This mount session is intended as being a pass through for when local files are used. The same API's for `#add` from MiqGenericMountSession are still usable for this class, and it will just write to the local file system instead. This also allows us to test the file splitting code without needing a mount session in place to do so.
This is the top level class for Object Storage based file storages, which will include types like s3 and FTP. Doesn't do much, but shared methods between all of the Object Storage classes will be put here.
Converts MiqS3Session to an MiqObjectStorage subclass, MiqS3Storage. A decent amount here didn't change, but it updates the `#add` and `#download` methods to use the MiqFileStorage::Interface and instead override `#upload_single` and `#download_single`. Many of the tests didn't make it over since a lot of it was in regards to "mounting", which ObjectStorage classes don't do and is now obsolete, as well as cleaned up MiqGenericMountSession from any references that were s3 specific. Also dried up the code a bit from what was implemented in MiqS3Session. Regarding the elephant in the room... ------------------------------------- Yes, I backported Aws::S3::MultipartStreamUploader from the v3 portion of the aws-sdk as part of this commit. Some form of "upload streaming" was necessary for file splitting to work. I could have implemented something myself with probably a little less code, but what was already part of the v3 API, is probably tested extensively, and works with the v2 Seahorse client and lib made more sense to implement via this way instead of trying to role my own. It is a lot of extra code, but I have a flag in place for when we do upgrade to aws-sdk v3 in the future, an error should be raised in the test suite to have this patch removed.
4877422
to
f3e3e9c
Compare
Checked commits NickLaMuro/manageiq-gems-pending@1c5c8c5~...f3e3e9c with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0 lib/gems/pending/util/miq_file_storage.rb
lib/gems/pending/util/object_storage/miq_s3_storage.rb
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work here @NickLaMuro
|
||
def s3 | ||
require 'aws-sdk' | ||
require 'util/extensions/aws-sdk/s3_upload_stream_patch' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bah... this means that this didn't get loaded in the specs... which would have made things easier...
Oh well I guess, we caught the PR updating this, so I guess all is good.
Update: Currently built off of #360 (will be implementing with that code soon)
Update: Also built off of #365. #360 might not stay as part of this PR, but currently including it here as well.
Update: Rebased in a lot of the
[WIP]
/[FIXUP]
commits, and removed #360 from this PR (will open up a separate PR to implement FTP).This introduces a higher level abstraction above
MiqGenericMountSession
which allows for a common API between mounted file systems, and what I have called in this branch nameUploadTarget
s (might renamed toObjectStorage
).Currently Implemented
MiqFileStorage
andMiqFileStorage::Interface
MiqFileStorage
will be what is actually interacted with by the user (top level API still in the works)MiqFileStorage::Interface
is what is the super class forMiqGenericMountSession
andMiqObjectStore
MiqGenericMountSession
inherit and conform to theMiqFileStorage::Interface
MiqLocalMountSession
, which allows local files to also use this interfaceMiqFileStorage::Interface
classesTODO
Possibly these will end up as follow up PRs, but regardless, the remaining TODO items for this repo is the following:
MiqObjectStore
subclassMiqS3Session
to live underMiqObjectStore
(MiqS3ObjectStore
maybe?)MiqS3Storage
Decided to skip doing the following:
Implement the high level interface forMiqFileStorage
(.add
,.download
, etc.)AddMiqFtpObjectStore